/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.snb.play.dwebtoon.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.snb.play.dwebtoon.data.JSonDataObjectBase;

/**
 * Android向けのO/RMを提供します。
 * 
 * @author sonix - http://www.sonix.asia
 * @since JDK1.5 Android Level 3
 * 
 */
public class Abatis extends SQLiteOpenHelper {
	// ADD BY BUM
	public String CREATE_SQL;

	/**
	 * Debug TAG名
	 */
	private static final String TAG = "aBatis";

	/**
	 * DBを初期化するSQLID
	 */
	private static final String INIT_CREATE_SQL = "abatis_init";

	/**
	 * アプリversion
	 */
	private static final String VERSION_FOR_UPGRADE = "abatis_version";

	/**
	 * Default DB file name
	 */
	private static final String DB_FILE_NAME = "database.db";

	/**
	 * SQLiteDatabase object
	 */
	public static SQLiteDatabase dbObj;

	public void begin() {
		getDbObject();
	}

	public void end() {
		if (dbObj != null && dbObj.isOpen())
			dbObj.close();
	}

	/**
	 * Context object
	 */
	private Context context;

	/**
	 * Upgrade Flag
	 */
	private boolean isUpgrade = false;

	/**
	 * Default DB file nameを利用するConstructor
	 * 
	 * @param context
	 *            呼び出し元Contextオブジェクト
	 * 
	 */
	// public Abatis(Context context) {
	// super(context, DB_FILE_NAME, null,
	// Integer.parseInt(context.getResources().getString(
	// context.getResources().getIdentifier(VERSION_FOR_UPGRADE, "string",
	// context.getPackageName()))));
	// this.context = context;
	// }

	/**
	 * 指定DB file nameを利用するConstructor
	 * 
	 * @param context
	 *            呼び出し元Contextオブジェクト
	 * @param dbName
	 *            生成するDB file name
	 * 
	 */
	public Abatis(Context context, String dbName, String initStr) {
		super(context, dbName.concat(".db"), null, Integer.parseInt(context.getResources().getString(
				context.getResources().getIdentifier(VERSION_FOR_UPGRADE, "string", context.getPackageName()))));
		CREATE_SQL = initStr;
		this.context = context;
	}

	/**
	 * DB connector
	 * 
	 * @param db
	 *            SQLiteDatabase object
	 * 
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		// int pointer = context.getResources().getIdentifier(INIT_CREATE_SQL,
		// "string", context.getPackageName());
		// if (pointer == 0) {
		// Logger.e(TAG, "undefined sql id - initialize");
		// } else {
		String[] createTabelSqls = CREATE_SQL.split(";");
		for (String sql : createTabelSqls) {
			if (sql.length() > 1) {
				Logger.d(TAG, "SQL [" + sql + "]");
				db.execSQL(sql + ";");
			}
		}
		// }
	}

	/**
	 * for upgrade
	 * 
	 * @param db
	 *            SQLiteDatabase object
	 * @param oldVersion
	 *            old version value
	 * @param newVersion
	 *            new version value
	 * 
	 */
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		isUpgrade = true;
	}

	/**
	 * 指定したSQLIDにparameterをmappingして、クエリする。結果mapを返却。
	 * 
	 * <p>
	 * mappingの時、parameterが足りない場合はnullを返す。 また、結果がない場合nullを返す。
	 * </p>
	 * 
	 * @param sqlId
	 *            SQLID
	 * @param bindParams
	 *            sql parameter
	 * 
	 * @return Map<String, Object> result
	 */
	public Map<String, Object> executeForMap(String sqlId, Map<String, Object> bindParams) {
		getDbObject();
		int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
		if (pointer == 0) {
			Logger.e(TAG, "undefined sql id");
			return null;
		}
		String sql = context.getResources().getString(pointer);
		if (bindParams != null) {
			Iterator<String> mapIterator = bindParams.keySet().iterator();
			while (mapIterator.hasNext()) {
				String key = mapIterator.next();
				Object value = bindParams.get(key);
				sql = sql.replaceAll("#" + key.toLowerCase() + "#", value == null ? null : "'" + value.toString() + "'");
			}
		}
		if (sql.indexOf('#') != -1) {
			Logger.e(TAG, "undefined parameter");
			return null;
		}
		Cursor cursor = dbObj.rawQuery(sql, null);
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		if (cursor == null) {
			return null;
		}
		String[] columnNames = cursor.getColumnNames();
		while (cursor.moveToNext()) {
			Map<String, Object> map = new HashMap<String, Object>();
			int i = 0;
			for (String columnName : columnNames) {
				map.put(columnName, cursor.getString(i));
				i++;
			}
			mapList.add(map);
		}
		if (mapList.size() <= 0) {
			return null;
		}
		cursor.close();
		// dbObj.close();
		return mapList.get(0);
	}

	/**
	 * 指定したSQLIDにparameterをmappingして、クエリする。結果mapをリストで返却。
	 * 
	 * <p>
	 * mappingの時、parameterが足りない場合はnullを返す。
	 * </p>
	 * 
	 * @param sqlId
	 *            SQLID
	 * @param bindParams
	 *            sql parameter
	 * 
	 * @return List<Map<String, Object>> result
	 */
	public List<Map<String, Object>> executeForMapList(String sqlId, Map<String, Object> bindParams) {
		getDbObject();
		int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
		if (pointer == 0) {
			Logger.e(TAG, "undefined sql id");
			return null;
		}
		String sql = context.getResources().getString(pointer);
		if (bindParams != null) {
			Iterator<String> mapIterator = bindParams.keySet().iterator();
			while (mapIterator.hasNext()) {
				String key = mapIterator.next();
				Object value = bindParams.get(key);
				sql = sql.replaceAll("#" + key.toLowerCase() + "#", value == null ? null : "'" + value.toString() + "'");
			}
		}
		if (sql.indexOf('#') != -1) {
			Logger.e(TAG, "undefined parameter");
			return null;
		}
		Cursor cursor = dbObj.rawQuery(sql, null);
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		if (cursor == null) {
			return null;
		}
		String[] columnNames = cursor.getColumnNames();
		while (cursor.moveToNext()) {
			Map<String, Object> map = new HashMap<String, Object>();
			int i = 0;
			for (String columnName : columnNames) {
				map.put(columnName, cursor.getString(i));
				i++;
			}
			mapList.add(map);
		}
		cursor.close();
		// dbObj.close();
		return mapList;
	}

	public int executeForgetSize(String sql) {
		getDbObject();
		int lSize = 0;
		Cursor cursor = dbObj.rawQuery(sql, null);
		if (cursor == null) {
			return 0;
		}
		cursor.moveToFirst();
		lSize = cursor.getInt(0);
		cursor.close();
		// dbObj.close();
		return lSize;
	}

	// ADD BY BUM
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T> T executeForBeanDinamicSql(String sql, Map<String, Object> bindParams, Class bean) {
		getDbObject();
		// int pointer = context.getResources().getIdentifier(sqlId, "string",
		// context.getPackageName());
		// if (pointer == 0) {
		// Logger.e(TAG, "undefined sql id");
		// return null;
		// }
		// String sql = context.getResources().getString(pointer);
		if (bindParams != null) {
			Iterator<String> mapIterator = bindParams.keySet().iterator();
			while (mapIterator.hasNext()) {
				String key = mapIterator.next();
				Object value = bindParams.get(key);
				sql = sql.replaceAll("#" + key.toLowerCase() + "#", value == null ? null : "'" + value.toString() + "'");
			}
		}
		if (sql.indexOf('#') != -1) {
			Logger.e(TAG, "undefined parameter");
			return null;
		}
		Cursor cursor = dbObj.rawQuery(sql, null);
		List<T> objectList = new ArrayList<T>();
		if (cursor == null) {
			return null;
		}
		String[] columnNames = cursor.getColumnNames();
		List<String> dataNames = new ArrayList<String>();
		for (String columnName : columnNames) {
			dataNames.add(chgDataName(columnName));
		}
		T beanObj = null;
		// get bean class package
		Package beanPackage = bean.getPackage();
		while (cursor.moveToNext()) {
			Map<String, Object> map = new HashMap<String, Object>();
			int i = 0;
			for (String dataName : dataNames) {
				map.put(dataName, cursor.getString(i));
				i++;
			}
			JSONObject json = new JSONObject(map);
			try {
				beanObj = (T) parse(json.toString(), bean, beanPackage.getName());
			} catch (Exception e) {
				Logger.d(TAG, e.toString());
				return null;
			}
			objectList.add(beanObj);
		}
		if (objectList.size() <= 0) {
			return null;
		}
		cursor.close();
		// dbObj.close();
		return objectList.get(0);
	}

	/**
	 * 指定したSQLIDにparameterをmappingして、クエリする。結果beanで返却。
	 * 
	 * <p>
	 * mappingの時、parameterが足りない場合はnullを返す。 また、結果がない場合nullを返す。
	 * </p>
	 * 
	 * @param sqlId
	 *            SQLID
	 * @param bindParams
	 *            sql parameter
	 * @param bean
	 *            bean class of result
	 * 
	 * @return List<Map<String, Object>> result
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T> T executeForBean(String sql, Map<String, Object> bindParams, Class bean) {
		Cursor cursor = dbObj.rawQuery(sql, null);
		List<T> objectList = new ArrayList<T>();
		if (cursor == null) {
			return null;
		}
		String[] columnNames = cursor.getColumnNames();
		List<String> dataNames = new ArrayList<String>();
		for (String columnName : columnNames) {
			dataNames.add(chgDataName(columnName));
		}
		T beanObj = null;
		// get bean class package
		Package beanPackage = bean.getPackage();
		while (cursor.moveToNext()) {
			Map<String, Object> map = new HashMap<String, Object>();
			int i = 0;
			for (String dataName : dataNames) {
				map.put(dataName, cursor.getString(i));
				i++;
			}
			JSONObject json = new JSONObject(map);
			try {
				beanObj = (T) parse(json.toString(), bean, beanPackage.getName());
			} catch (Exception e) {
				Logger.d(TAG, e.toString());
				return null;
			}
			objectList.add(beanObj);
		}
		if (objectList.size() <= 0) {
			return null;
		}
		cursor.close();
		// dbObj.close();
		return objectList.get(0);
	}

	public <T> T executeForBeanNext(String sql, Map<String, Object> bindParams, Class bean) {
		Cursor cursor = dbObj.rawQuery(sql, null);
		List<T> objectList = new ArrayList<T>();
		if (cursor == null) {
			return null;
		}
		String[] columnNames = cursor.getColumnNames();
		List<String> dataNames = new ArrayList<String>();
		for (String columnName : columnNames) {
			dataNames.add(chgDataName(columnName));
		}
		T beanObj = null;
		// get bean class package
		Package beanPackage = bean.getPackage();
		while (cursor.moveToNext()) {
			Map<String, Object> map = new HashMap<String, Object>();
			int i = 0;
			for (String dataName : dataNames) {
				map.put(dataName, cursor.getString(i));
				i++;
			}
			JSONObject json = new JSONObject(map);
			try {
				beanObj = (T) parse(json.toString(), bean, beanPackage.getName());
			} catch (Exception e) {
				Logger.d(TAG, e.toString());
				return null;
			}
			objectList.add(beanObj);
		}
		if (objectList.size() <= 0) {
			return null;
		}
		cursor.close();
		// dbObj.close();
		if (objectList.size() > 1)
			return objectList.get(1);
		return null;
	}

	/**
	 * 指定したSQLIDにparameterをmappingして、クエリする。結果beanをリストで返却。
	 * 
	 * <p>
	 * mappingの時、parameterが足りない場合はnullを返す。
	 * </p>
	 * 
	 * @param sqlId
	 *            SQLID
	 * @param bindParams
	 *            sql parameter
	 * @param bean
	 *            bean class of result
	 * 
	 * @return List<Map<String, Object>> result
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public <T> List<T> executeForBeanList(String sql, Map<String, Object> bindParams, Class bean) {
		getDbObject();
		Logger.d(TAG, "executeForBeanList  == " + sql);
		Cursor cursor = dbObj.rawQuery(sql, null);
		List<T> objectList = new ArrayList<T>();
		if (cursor == null) {
			return null;
		}

		String[] columnNames = cursor.getColumnNames();
		List<String> dataNames = new ArrayList<String>();
		for (String columnName : columnNames) {
			dataNames.add(columnName);
		}
		T beanObj = null;

		Package beanPackage = bean.getPackage();
		while (cursor.moveToNext()) {
			Map<String, Object> map = new HashMap<String, Object>();
			int i = 0;
			for (String dataName : dataNames) {
				map.put(dataName, cursor.getString(i));
				i++;
			}
			JSONObject json = new JSONObject(map);
			try {
				beanObj = (T) parse(json.toString(), bean, beanPackage.getName());
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
			objectList.add(beanObj);
		}
		cursor.close();
		// dbObj.close();
		return objectList;
	}

	// ADD BY BUM
	public int executeDirectSql(String sql) {
		int row = 0;
		try {
			dbObj.execSQL(sql);
			row += 1;
		} catch (SQLException e) {
			if (Logger.LOGGER_ENABLED)
				e.printStackTrace();
			return row;
		}
		return row;
	}

	public int executeDirectSqlNonClose(String sql) {

		int row = 0;
		try {
			Logger.d(TAG, sql);
			dbObj.execSQL(sql);
			row += 1;
		} catch (SQLException e) {
			if (Logger.LOGGER_ENABLED)
				e.printStackTrace();
			return row;
		}

		return row;
	}

	/**
	 * 指定したSQLIDにparameterをmappingして、実行する。
	 * 
	 * <p>
	 * mappingの時、parameterが足りない場合は0を返す。
	 * </p>
	 * 
	 * @param sqlId
	 *            SQLiteDatabase object
	 * @param bindParams
	 *            old version value
	 * 
	 * @return int 実行によって影響をもらった行数
	 */
	public int execute(String sqlId, Map<String, Object> bindParams) {
		getDbObject();
		int row = 0;
		int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
		if (pointer == 0) {
			Logger.e(TAG, "undefined sql id");
			return row;
		}
		String sql = context.getResources().getString(pointer);
		if (bindParams != null) {
			Iterator<String> mapIterator = bindParams.keySet().iterator();
			while (mapIterator.hasNext()) {
				String key = mapIterator.next().toLowerCase();
				Object value = bindParams.get(key);
				sql = sql.replaceAll("#" + key.toLowerCase() + "#", value == null ? null : "'" + value.toString() + "'");
			}
		}

		Logger.d(TAG, ">>> SQL : " + sql);

		if (sql.indexOf('#') != -1) {
			Logger.e(TAG, "undefined parameter");
			return row;
		}
		try {
			dbObj.execSQL(sql);
			// dbObj.close();
			row += 1;
		} catch (SQLException e) {
			return row;
		}
		return row;
	}

	/**
	 * Execute.
	 * 
	 * @author jhk
	 * @param sqlId
	 *            the sql id
	 * @return the int
	 */
	public int execute(String sqlId) {
		return execute(sqlId, null);
	}

	/**
	 * Execute for params list.
	 * 
	 * @author jhk
	 * @param sqlId
	 *            the sql id
	 * @param paramsList
	 *            the params list
	 * @return the int
	 */
	public int executeForParamsList(String sqlId, List<Map<String, Object>> paramsList) {
		getDbObject();
		int row = 0;
		int pointer = context.getResources().getIdentifier(sqlId, "string", context.getPackageName());
		if (pointer == 0) {
			Logger.e(TAG, "Undefined SQL ID");
			return row;
		}

		String sql = context.getResources().getString(pointer);

		if (paramsList != null) {
			dbObj.beginTransaction();
			try {
				for (Map<String, Object> bindParams : paramsList) {
					String strExecSQL = new String(sql);
					if (bindParams != null) {
						Iterator<String> mapIterator = bindParams.keySet().iterator();
						while (mapIterator.hasNext()) {
							String key = mapIterator.next().toLowerCase();
							Object value = bindParams.get(key);
							strExecSQL = strExecSQL.replaceAll("#" + key.toLowerCase() + "#", value == null ? null : "'" + value.toString() + "'");
						}
					}

					Logger.d(TAG, "ExecSQL [" + strExecSQL + "]");

					if (strExecSQL.indexOf('#') != -1) {
						Logger.e(TAG, "Undefined Parameter");
						return row;
					}

					try {
						dbObj.execSQL(strExecSQL);
						row++;
					} catch (SQLException e) {
						return row;
					}
				}
				dbObj.setTransactionSuccessful();
			} catch (SQLException e) {
				Logger.e(TAG, e.toString(), e);
			} finally {
				dbObj.endTransaction();
				// dbObj.close();
			}
		}
		return row;
	}

	/**
	 * SQLiteDatabase Objectを取得する。
	 * 
	 * @return SQLiteDatabase SQLiteDatabase Object
	 */
	protected SQLiteDatabase getDbObject() {
		if (dbObj == null || !dbObj.isOpen()) {
			dbObj = getWritableDatabase();
		}
		return dbObj;
	}

	/**
	 * JsonStringからBeanに変換する。
	 * 
	 * @param jsonStr
	 *            JSON String
	 * @param beanClass
	 *            Bean class
	 * @param basePackage
	 *            Base package name which includes all Bean classes
	 * @return Object Bean
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Object parse(String jsonStr, Class beanClass, String basePackage) throws Exception {
		Object obj = null;
		JSONObject jsonObj = new JSONObject(jsonStr);
		// Check bean object
		if (beanClass == null) {
			Logger.d(TAG, "Bean class is null");
			return null;
		}
		// Read Class member fields
		Field[] props = beanClass.getDeclaredFields();
		if (props == null || props.length == 0) {
			Logger.d(TAG, "Class" + beanClass.getName() + " has no fields");
			return null;
		}
		// Create instance of this Bean class
		obj = beanClass.newInstance();
		// Set value of each member variable of this object
		for (int i = 0; i < props.length; i++) {
			String fieldName = props[i].getName();
			// Skip fields
			switch (props[i].getModifiers()) {
			// @formatter:off
	    case Modifier.PUBLIC: {
		JSonDataObjectBase.setMemberFiled(obj, jsonObj, fieldName);
	    }
		continue;
	    case Modifier.STATIC:
		continue;
	    case Modifier.PUBLIC + Modifier.STATIC + Modifier.FINAL:
		continue;
	    case Modifier.PRIVATE + Modifier.STATIC + Modifier.FINAL:
		continue;
		// @formatter:on
			}
			// Date Type of Field
			Class type = props[i].getType();
			String typeName = type.getName();
			// Check for Custom type
			if (typeName.equals("int")) {
				Class[] parms = { type };
				Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
				m.setAccessible(true);
				// Set value
				try {
					m.invoke(obj, jsonObj.getInt(fieldName));
				} catch (Exception ex) {
					Logger.d(TAG, ex.getMessage());
				}
			} else if (typeName.equals("long")) {
				Class[] parms = { type };
				Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
				m.setAccessible(true);
				// Set value
				try {
					m.invoke(obj, jsonObj.getLong(fieldName));
				} catch (Exception ex) {
					Logger.d(TAG, ex.getMessage());
				}
			} else if (typeName.equals("java.lang.String")) {
				Class[] parms = { type };
				Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
				m.setAccessible(true);
				// Set value
				try {
					m.invoke(obj, jsonObj.getString(fieldName));
				} catch (Exception ex) {
					Logger.d(TAG, ex.getMessage());
				}
			} else if (typeName.equals("double")) {
				Class[] parms = { type };
				Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
				m.setAccessible(true);
				// Set value
				try {
					m.invoke(obj, jsonObj.getDouble(fieldName));
				} catch (Exception ex) {
					Logger.d(TAG, ex.getMessage());
				}
			} else if (type.getName().equals(List.class.getName()) || type.getName().equals(ArrayList.class.getName())) {
				// Find out the Generic
				String generic = props[i].getGenericType().toString();
				if (generic.indexOf("<") != -1) {
					String genericType = generic.substring(generic.lastIndexOf("<") + 1, generic.lastIndexOf(">"));
					if (genericType != null) {
						JSONArray array = null;
						try {
							array = jsonObj.getJSONArray(fieldName);
						} catch (Exception ex) {
							Logger.d(TAG, ex.getMessage());
							array = null;
						}
						if (array == null) {
							continue;
						}
						ArrayList arrayList = new ArrayList();
						for (int j = 0; j < array.length(); j++) {
							arrayList.add(parse(array.getJSONObject(j).toString(), Class.forName(genericType), basePackage));
						}
						// Set value
						Class[] parms = { type };
						Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
						m.setAccessible(true);
						m.invoke(obj, arrayList);
					}
				} else {
					// No generic defined
					generic = null;
				}
			} else if (typeName.startsWith(basePackage)) {
				Class[] parms = { type };
				Method m = beanClass.getDeclaredMethod(getBeanMethodName(fieldName, 1), parms);
				m.setAccessible(true);
				// Set value
				try {
					JSONObject customObj = jsonObj.getJSONObject(fieldName);
					if (customObj != null) {
						m.invoke(obj, parse(customObj.toString(), type, basePackage));
					}
				} catch (JSONException ex) {
					Logger.d(TAG, ex.getMessage());
				}
			} else {
				// Skip
				Logger.d(TAG, "Field " + fieldName + "#" + typeName + " is skip");
			}
		}
		return obj;
	}

	/**
	 * BeanClass fields名からmethod名を取得する。
	 * 
	 * @param fieldName
	 * @param type
	 * @return String MethodName
	 */
	private String getBeanMethodName(String fieldName, int type) {
		if (fieldName == null || fieldName == "") {
			return "";
		}
		String methodName = "";
		if (type == 0) {
			methodName = "get";
		} else {
			methodName = "set";
		}
		methodName += fieldName.substring(0, 1).toUpperCase();
		if (fieldName.length() == 1) {
			return methodName;
		}
		methodName += fieldName.substring(1);
		return methodName;
	}

	/**
	 * Databaseカラム名をjava bean名に変換する。
	 * 
	 * @param targetStr
	 *            databaseカラム名
	 * @return String bean data名
	 */
	private String chgDataName(String targetStr) {
		Pattern p = Pattern.compile("_([a-z])");
		Matcher m = p.matcher(targetStr.toLowerCase());

		StringBuffer sb = new StringBuffer(targetStr.length());
		while (m.find()) {
			m.appendReplacement(sb, m.group(1).toUpperCase());
		}
		m.appendTail(sb);
		return sb.toString();
	}

	/**
	 * アプリUpgrade判定
	 * 
	 * @return boolean Upgradeフラグ
	 */
	public boolean isUpgrade() {
		// log and set upgrade flag
		Logger.d(TAG, String.valueOf(getDbObject().getVersion()));
		return isUpgrade;
	}
}
